package cn.renxuan.redis;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import cn.renxuan.CommonUtil;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.support.ConnectionPoolSupport;

public class LettuceRedisHelper {
    private static RedisClient client;

    private static GenericObjectPool<StatefulRedisConnection<String, String>> pool = null;

    public static void init() throws IOException {
        String profileName = System.getenv("SPRING_PROFILES_ACTIVE");
        String utilityConfigFileName = String.format("utility%s.properties",
                profileName == null || profileName.isBlank() ? "" : "-" + profileName);

        CommonUtil.printThreadLog("开始加载utility配置文件：" + utilityConfigFileName);
        // 如果没有配置文件，则使用默认的jdbc.properties

        // 读取本地数据库配置文件
        InputStream rs = LettuceRedisHelper.class.getClassLoader().getResourceAsStream(utilityConfigFileName);
        // 本地文件流加载到Properties对象中
        Properties ps = new Properties();
        ps.load(rs);

        // 从配置创建 RedisURI
        String redisPwd = ps.getProperty("spring.redis.password");
        int dbNum = Integer.parseInt(ps.getProperty("spring.redis.database", "0"));
        RedisURI redisUri = RedisURI.builder()
                .withHost(ps.getProperty("spring.redis.host"))
                .withPort(Integer.parseInt(ps.getProperty("spring.redis.port")))
                .withPassword(null == redisPwd || redisPwd.isBlank() ? null
                        : redisPwd.toCharArray())
                .withDatabase(dbNum)
                .build();
        if (redisUri != null) {
            init(redisUri);
        } else {
            CommonUtil.printThreadLog("未找到Redis配置，无法初始化LettuceRedisHelper");
        }

    }

    public static void init(String redisUri) {
        if (client == null) {
            client = RedisClient.create(redisUri);
        }
        if (client != null) {
            createRedisPool(client);
        }
    }

    private static void createRedisPool(RedisClient client) {
        // 创建连接池配置
        GenericObjectPoolConfig<StatefulRedisConnection<String, String>> poolConfig = new GenericObjectPoolConfig<>();
        poolConfig.setMaxTotal(10); // 最大连接数
        poolConfig.setMaxIdle(5); // 最大空闲连接数

        // 创建连接池
        pool = ConnectionPoolSupport
                .createGenericObjectPool(client::connect, poolConfig);
    }

    public static void init(RedisURI redisUri) {
        if (client == null) {
            client = RedisClient.create(redisUri);
        }

        if (client != null) {
            createRedisPool(client);
        }
    }

    public static boolean hset(String key, String field, String value) throws Exception {
        boolean isSetSuccess = false;
        if (pool != null) {
            try (StatefulRedisConnection<String, String> connection = pool.borrowObject()) {
                RedisCommands<String, String> syncCommands = connection.sync();
                isSetSuccess = syncCommands.hset(key, field, value);
            }
        }
        return isSetSuccess;
    }

    public static boolean hsetnx(String key, String field, String value) throws Exception {
        boolean isSetSuccess = false;
        if (pool != null) {
            try (StatefulRedisConnection<String, String> connection = pool.borrowObject()) {
                RedisCommands<String, String> syncCommands = connection.sync();
                isSetSuccess = syncCommands.hsetnx(key, field, value);
            }
        }
        return isSetSuccess;
    }

    public static String hget(String key, String field) throws Exception {
        String value = null;
        if (pool != null) {
            try (StatefulRedisConnection<String, String> connection = pool.borrowObject()) {
                RedisCommands<String, String> syncCommands = connection.sync();
                value = syncCommands.hget(key, field);
            }
        }
        return value;
    }

    public static long hset(String key, Map<String, String> fv) throws Exception {
        long setCount = 0;
        if (pool != null) {
            try (StatefulRedisConnection<String, String> connection = pool.borrowObject()) {
                RedisCommands<String, String> syncCommands = connection.sync();
                setCount = syncCommands.hset(key, fv);
            }
        }
        return setCount;
    }

    public static Map<String, String> hgetAll(String key) throws Exception {
        Map<String, String> map = null;
        if (pool != null) {
            try (StatefulRedisConnection<String, String> connection = pool.borrowObject()) {
                RedisCommands<String, String> syncCommands = connection.sync();
                map = syncCommands.hgetall(key);
            }
        }
        return map;
    }

    public static <TResult> TResult get(String key) {
        try (StatefulRedisConnection<String, String> connection = client.connect()) {
            RedisCommands<String, TResult> commands = (RedisCommands<String, TResult>) connection.<TResult>sync();

            return commands.get(key);
            // // 字符串操作
            // commands.set("lettuceKey", "lettuceValue");
            // String value = commands.get("lettuceKey");
            // System.out.println(value); // 输出: lettuceValue

            // // 发布/订阅
            // commands.publish("channel", "Hello, Redis!");
        }
    }

}
